from threading import Thread

import qrcode
import requests
from django.db import transaction
from django.db.models import Q, F
from django.shortcuts import render, redirect
from .models import *
from rest_framework.views import APIView, Response
from django.http.response import JsonResponse, HttpResponse
from mydjango.settings import FILE_ROOT
import time
import jwt
import json
from mydjango.settings import Echarts_Appid
import httpx
from .sers import *
import datetime
import time
import snowflake.client


# Create your views here.

class UserView(APIView):
    def post(self, request):
        data = request.data
        User.objects.create(username=data['username'], password=data['password'], addr=data['addr'],
                            id_number=data['number'],
                            name=data['name'])
        return Response({'msg': '注册成功'})


import os
import shutil
import random


class FileUpload(APIView):
    def post(self, request):
        file_obj = request.data.get('file')
        file_name = request.data.get('name')
        f_name = request.data.get('f_name')

        path_lis = os.listdir(FILE_ROOT)

        # 创建切片接收目录
        if not f_name in path_lis:
            os.mkdir(FILE_ROOT + '\\{}'.format(f_name))

        filename = FILE_ROOT + '\\{}\\'.format(f_name) + file_name

        with open(filename, 'wb') as f:
            for line in file_obj:
                f.write(line)
        return JsonResponse({'msg': '上传成功'})

    def put(self, request):
        file_num = request.data.get('index')
        file_name = request.data.get('filename')

        files_seve_url = FILE_ROOT + '\\UploadFile\\' + file_name
        files_read_url = FILE_ROOT + '\\{}\\'.format(file_name)

        # 拼接文件
        with open(files_seve_url, 'ab') as f:
            for i in range(int(file_num)):
                url = files_read_url + file_name + str(i)

                with open(url, 'rb') as r:
                    line = r.read()
                    f.write(line)

        # 删除分片目录
        shutil.rmtree(files_read_url)

        return Response({'msg': '拼接完成'})


class LoginView(APIView):
    def post(self, request):
        username = request.data.get('username')
        password = request.data.get('password')
        user = User.objects.filter(username=username, password=password).first()

        if user:
            token = jwt.encode({'uid': user.id}, '123456')

            return Response({'msg': '登录成功', 'token': token, 'code': 200})

        return Response({'msg': '账号或密码错误', 'code': 400})


import redis
from dwebsocket.decorators import accept_websocket


def lens(request):
    r = redis.Redis(decode_responses=True)
    if r.exists('myset'):
        r.sadd('myset', request.META['REMOTE_ADDR'])

    else:
        r.expire('myset', 300)
        r.sadd('myset', request.META['REMOTE_ADDR'])

    return JsonResponse({'msg': r.scard('myset')})


@accept_websocket
def LoginLen(request):
    r = redis.Redis(decode_responses=True)
    if request.is_websocket():
        while True:
            if r.exists('myset'):
                r.sadd('myset', request.META['REMOTE_ADDR'])

            else:
                r.sadd('myset', request.META['REMOTE_ADDR'])
                r.expire('myset', 30)
            request.websocket.send(json.dumps({'len': r.scard('myset')}))
            time.sleep(5)


class MyEcharts(APIView):
    def get(self, request):
        data = HuiSer(Hui.objects.all())[:5][::-1]  # 从数据库中读取数据

        # 获取数据后判断数据是否更新
        y = datetime.datetime.strptime(data[0]['update'], '%Y-%m-%d')
        z = str(datetime.datetime.now()).split(' ')[0]
        z = datetime.datetime.strptime(z, '%Y-%m-%d')
        if (z - datetime.timedelta(days=1)) == y:
            # 判断到数据未更新，更新数据，返回库中数据
            url = 'http://op.juhe.cn/onebox/exchange/query?key=' + Echarts_Appid
            data = eval(httpx.get(url).text)
            Hui.objects.create(update=str(data['result']['update']), json=str(data['result']['list']))

        date = []
        huilv = []

        for i in data:
            date.append(i['update'])
            huilv.append(i['json'][0][2])

        return Response({'date': date, 'huilv': huilv})


@accept_websocket
def RTExchangeRate(request):
    url = 'http://op.juhe.cn/onebox/exchange/currency?key={}&from=USD&to=CNY'.format(Echarts_Appid)
    if request.is_websocket():
        # 接收到连接请求，直接向数据库发送请求并，获取距离下一分钟还有多少秒，延迟后进入循环
        d_s = 59 - int(time.time()) % 60
        # 获取当前日期
        t = datetime.date.today()
        # 获取当天的数据
        data = RTHuiSer(RTHui.objects.filter(date=str(t)))
        # 发送数据
        js = {
            'hui': [i['json'] for i in data],
            'time': [i['time'] for i in data],
            'date': [i['date'] for i in data],
        }
        request.websocket.send(json.dumps({'data': js, 'state': 0}))
        # 卡住程序，等待下一分钟到来
        time.sleep(d_s)
        while True:
            # 开始无限循环推送

            # 请求数据
            data = eval(httpx.get(url).text)
            # 进行入库操作
            dateti = data['result'][0]['updateTime']
            RTHui.objects.create(
                date=dateti.split(' ')[0],
                time=dateti.split(' ')[1],
                json=data['result'][0]['exchange']
            )
            # 提取数据
            js = {
                'date': dateti.split(' ')[0],
                'time': dateti.split(' ')[1],
                'json': data['result'][0]['exchange']
            }
            # 推送到前端
            request.websocket.send(json.dumps({'data': js, 'state': 1}))
            # 休眠，等待一分钟后再次推送
            time.sleep(60)


from .Vzhifhu import *
from mydjango.settings import V_id, V_apips, V_appid


class wx_pay(APIView):
    # 实现单例模式
    _instance = None

    def __new__(cls, *args, **kw):
        if not cls._instance:
            cls._instance = super(wx_pay, cls).__new__(cls, *args, **kw)

        return cls._instance

    def post(self, request):
        url = 'https://api.mch.weixin.qq.com/pay/unifiedorder'  # 微信扫码支付接口
        key = V_apips  # 商户api秘钥
        total_fee = eval(request.data.get('total'))  # 支付金额，单位分
        body = '123321'  # 商品描述
        snowflake.client.setup('127.0.0.1', 8910)
        out_trade_no = str(snowflake.client.get_guid())  # 生成雪花订单号

        params = {
            'appid': V_appid,  # APPID
            'mch_id': V_id,  # 商户号
            'notify_url': 'http://wxpay.v3u.cn/wx_back/',  # 支付域名回调地址
            'product_id': 'goods_%s' % random.randrange(100000, 999999),  # 商品编号
            'trade_type': 'NATIVE',  # 支付类型（扫码支付）
            'spbill_create_ip': '39.102.40.216',  # 发送请求服务器的IP地址
            'total_fee': total_fee,  # 订单总金额
            'out_trade_no': out_trade_no,  # 订单编号
            'body': body,  # 商品描述
            'nonce_str': 'ibuaiVcKdpRxkhJA'  # 字符串
        }
        sign = get_sign(params, key)  # 获取签名
        params.setdefault('sign', sign)  # 添加签名到参数字典
        xml = trans_dict_to_xml(params)  # 转换字典为XML
        response = requests.request('post', url, data=xml)  # 以POST方式向微信公众平台服务器发起请求
        data_dict = trans_xml_to_dict(response.content)  # 将请求返回的数据转为字典
        print(data_dict)
        qrcode_name = out_trade_no + '.png'  # 支付二维码图片保存路径
        if data_dict.get('return_code') == 'SUCCESS':  # 如果请求成功
            img = qrcode.make(data_dict.get('code_url'))  # 创建支付二维码片
            img.save(FILE_ROOT + '\\' + qrcode_name)  # 保存支付二维码
        return JsonResponse({'url': qrcode_name, 'order_id': out_trade_no})

    def get(self, request):
        # 统一订单查询接口

        url = "https://api.mch.weixin.qq.com/pay/orderquery"

        out_trade_no = request.GET.get('order_id')  # 支付后的商户订单号
        key = V_apips  # 商户api密钥

        params = {
            'appid': V_appid,  # APPID
            'mch_id': V_id,  # 商户号
            'out_trade_no': out_trade_no,  # 订单编号
            'nonce_str': 'ibuaiVcKdpRxkhJA'  # 随机字符串
        }
        sign = get_sign(params, key)  # 获取签名
        params.setdefault('sign', sign)  # 添加签名到参数字典
        xml = trans_dict_to_xml(params)  # 转换字典为XML
        response = requests.request('post', url, data=xml)  # 以POST方式向微信公众平台服务器发起请求
        data_dict = trans_xml_to_dict(response.content)  # 将请求返回的数据转为字典

        uid = jwt.decode(request.GET.get('uid'), '123456')['uid']

        if uid & 1 == 0:
            Order2.objects.create(uid=uid,
                                  order_id=out_trade_no,
                                  total=int(data_dict['total_fee']) / 100
                                  )
        else:
            Order1.objects.create(uid=uid,
                                  order_id=out_trade_no,
                                  total=int(data_dict['total_fee']) / 100
                                  )

        return HttpResponse(data_dict['trade_state_desc'])


import paypalrestsdk
from mydjango.settings import Paypal_User_Id, Paypal_User_Pswd


class Payment(APIView):
    # 实现单例模式
    _instance = None

    def __new__(cls, *args, **kw):
        if not cls._instance:
            cls._instance = super(wx_pay, cls).__new__(cls, *args, **kw)

        return cls._instance

    def post(self, request):
        paypalrestsdk.configure({
            "mode": "sandbox",  # sandbox代表沙盒
            "client_id": Paypal_User_Id,
            "client_secret": Paypal_User_Pswd})

        snowflake.client.setup('127.0.0.1', 8911)
        out_trade_no = str(snowflake.client.get_guid())  # 生成雪花订单号

        payment = paypalrestsdk.Payment({
            "intent": "sale",
            "payer": {
                "payment_method": "paypal"},
            "redirect_urls": {
                "return_url": "http://localhost:8080/palpay/pay/",  # 支付成功跳转页面
                "cancel_url": "http://localhost:8080/paypal/cancel/"},  # 取消支付页面
            "transactions": [{
                "amount": {
                    "total": request.data.get('total'),
                    "currency": "USD"},
                "description": "这是一个订单测试"}]})

        if payment.create():
            print("Payment created successfully")
            for link in payment.links:
                if link.rel == "approval_url":
                    approval_url = str(link.href)

                    snowflake.client.setup('127.0.0.1', 8911)
                    out_trade_no = str(snowflake.client.get_guid())  # 生成雪花订单号

                    token = request.GET.get('token')
                    uid = jwt.decode(token, '123456')['uid']

                    if uid & 1 == 0:
                        Order2.objects.create(uid=uid,
                                              order_id=out_trade_no,
                                              total=int(request.data.get('total')) / 100
                                              )
                    else:
                        Order1.objects.create(uid=uid,
                                              order_id=out_trade_no,
                                              total=int(request.data.get('total')) / 100
                                              )

                    return JsonResponse({'url': approval_url, 'code': 200})
        else:
            print(payment.error)
            return JsonResponse({'msg': "支付失败", 'code': '400'})


class OrderView(APIView):
    def get(self, request):
        token = request.GET.get('token')
        uid = jwt.decode(token, '123456')['uid']
        page = int(request.GET.get('page'))  # 页数

        if uid & 1 == 0:
            query = Order2.objects.filter(uid=uid)
        else:
            query = Order1.objects.filter(uid=uid)

        data = OrderSer(query)
        max_page = len(data) // 10  # 最大页数
        if len(data) % 10 > 0 or len(data) < 10:
            max_page += 1

        z_page = list(range(1, max_page))  # 页数列表
        if z_page == []:
            z_page.append(1)

        if page == max_page:
            data = data[len(data) % 10 - 1:]
        else:
            data = data[(page - 1) * 10:page * 10]

        return Response({'data': data, 'z_pang': z_page, 'max_page': max_page})


def OrderId(request):
    if request.method == 'GET':
        order_id = request.GET.get('order_id')
        o_db_id = bin(int(order_id))[42:52]
        if int(o_db_id) == 1:
            query = Order1.objects.filter(order_id=order_id)
        else:
            query = Order2.objects.filter(order_id=order_id)

        data = OrderSer(query)
        return JsonResponse({'info': data[0]})

    return HttpResponse('请求方式错误')


def GoodView(request):
    if request.method == 'POST':
        name = request.GET.get('name', None)
        if not name:
            return JsonResponse({'code': 400, 'massage': '确实必要参数'})

        Good.objects.create(name=name)
        return HttpResponse('添加成功')

    elif request.method == 'GET':
        name = request.GET.get('name', None)
        if not name:
            return JsonResponse({'code': 400, 'massage': '确实必要参数'})

        good = Good.objects.filter(name=name)
        if good:
            with transaction.atomic():
                # 创建保存点
                save_id = transaction.savepoint()
                good.update(number=F('number') - 1)

                if Good.objects.filter(name=name).first().number < 0:
                    transaction.savepoint_rollback(save_id)
                    return HttpResponse('库存不够')

                else:
                    return HttpResponse('请求成功')


from redis import Redis


@accept_websocket
def RankingListView(request):
    if request.is_websocket():
        r = Redis(decode_responses=True)
        while True:
            # 开始无限循环推送

            # 请求数据, 查询排行榜前50名数据
            data = r.zrevrange('RankingList', 0, 50, withscores=True)
            # 推送到前端
            request.websocket.send(json.dumps({'data': data}))
            # 休眠，等待一分钟后再次推送
            time.sleep(1)


# 排行榜添加接口
def RankingListAddView(request):
    if request.method == 'GET':
        r = Redis(decode_responses=True)
        num = request.GET.get("num", None)
        if num:
            print(num)
            r.zadd('RankingList', {num: int(num)})
            return HttpResponse('添加成功')

        return HttpResponse('添加失败')


def TransactionOrderAdd(request):
    if request.method == 'POST':
        token = request.data.get('token')
        uid = jwt.decode(token, '123456')['uid']
        order_type = request.data.get('order_type')
        price = request.data.get('price')
        number_shares = request.data.get('number_shares')

        TransactionOrder.objects.create(uid=uid, order_type=order_type, price=price, number_shares=number_shares)
        return HttpResponse('订单提交成功')


from .Transactions import *


class TransactionOrderView(APIView):
    def post(self, request):
        threaded = request.data.get('threaded', None)
        data = TransactionOrderSer(TransactionOrder.objects.all())

        if threaded:
            self.thread = Thread(target=run, args=(data,))
            self.thread.start()
        else:
            run(data)
